package com.linran.utils.lock.distribution.impl;

import com.linran.utils.lock.distribution.DistributionLockHandler;
import com.linran.utils.lock.pojo.result.LockResult;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;

/**
 * @author lin
 * @date 2020-07-13 13:43
 */
@Slf4j
@Component
public class MyDistributionLockHandler implements DistributionLockHandler {
    @Autowired
    private RedissonClient redissonClient;

    @Override
    public LockResult lock(String lockKey) {
        try {
            RLock lock = redissonClient.getLock(lockKey);
            //未获取到锁会被"阻塞"
            lock.lock();
            return LockResult.succ(lock);
        } catch (Exception e) {
            log.error("[加锁失败] " + e.getMessage() + " key:" + lockKey, e);
            return null;
        }
    }

    @Override
    public LockResult lock(String lockKey, int leaseTime) {
        try {
            RLock lock = redissonClient.getLock(lockKey);
            lock.lock(leaseTime, TimeUnit.SECONDS);
            return LockResult.succ(lock);
        } catch (Exception e) {
            log.error("[加锁失败] " + e.getMessage() + " key:" + lockKey, e);
            return null;
        }
    }

    @Override
    public LockResult lock(String lockKey, int leaseTime, TimeUnit unit) {
        try {
            RLock lock = redissonClient.getLock(lockKey);
            lock.lock(leaseTime, unit);
            return LockResult.succ(lock);
        } catch (Exception e) {
            log.error("[加锁失败] " + e.getMessage() + " key:" + lockKey, e);
            return null;
        }
    }

    @Override
    public LockResult tryLock(String lockKey, int waitTime, int leaseTime) {
        try {
            RLock lock = redissonClient.getLock(lockKey);
            boolean result = lock.tryLock(waitTime, leaseTime, TimeUnit.SECONDS);
            return LockResult.of(lock, result);
        } catch (Exception e) {
            log.error("[加锁失败] " + e.getMessage() + " key:" + lockKey, e);
            return null;
        }
    }

    @Override
    public LockResult tryLock(String lockKey, int waitTime, int leaseTime, TimeUnit unit) {
        try {
            RLock lock = redissonClient.getLock(lockKey);
            boolean result = lock.tryLock(waitTime, leaseTime, unit);
            return LockResult.of(lock, result);
        } catch (Exception e) {
            log.error("[加锁失败] " + e.getMessage() + " key:" + lockKey, e);
            return null;
        }
    }

    @Override
    public LockResult fairLock(String lockKey) {
        try {
            RLock fairLock = redissonClient.getFairLock(lockKey);
            fairLock.lock();
            return LockResult.succ(fairLock);
        } catch (Exception e) {
            log.error("[加锁失败] " + e.getMessage() + " key:" + lockKey, e);
            return null;
        }
    }

    @Override
    public LockResult fairLock(String lockKey, int leaseTime) {
        try {
            RLock fairLock = redissonClient.getFairLock(lockKey);
            fairLock.lock(leaseTime, TimeUnit.SECONDS);
            return LockResult.succ(fairLock);
        } catch (Exception e) {
            log.error("[加锁失败] " + e.getMessage() + " key:" + lockKey, e);
            return null;
        }
    }

    @Override
    public LockResult fairLock(String lockKey, int leaseTime, TimeUnit unit) {
        try {
            RLock fairLock = redissonClient.getFairLock(lockKey);
            fairLock.lock(leaseTime, unit);
            return LockResult.succ(fairLock);
        } catch (Exception e) {
            log.error("[加锁失败] " + e.getMessage() + " key:" + lockKey, e);
            return null;
        }
    }

    @Override
    public LockResult tryFairLock(String lockKey, int waitTime, int leaseTime) {
        try {
            RLock fairLock = redissonClient.getFairLock(lockKey);
            fairLock.tryLock(waitTime, leaseTime, TimeUnit.SECONDS);
            return LockResult.succ(fairLock);
        } catch (Exception e) {
            log.error("[加锁失败] " + e.getMessage() + " key:" + lockKey, e);
            return null;
        }
    }

    @Override
    public LockResult tryFairLock(String lockKey, int waitTime, int leaseTime, TimeUnit unit) {
        try {
            RLock fairLock = redissonClient.getFairLock(lockKey);
            fairLock.tryLock(waitTime, leaseTime, unit);
            return LockResult.succ(fairLock);
        } catch (Exception e) {
            log.error("[加锁失败] " + e.getMessage() + " key:" + lockKey, e);
            return null;
        }
    }

    @Override
    public LockResult lock(Collection<String> lockKeys) {
        return null;
    }

    @Override
    public LockResult lock(Collection<String> lockKeys, int timeout) {
        return null;
    }

    @Override
    public LockResult lock(Collection<String> lockKeys, int timeout, TimeUnit unit) {
        return null;
    }

    @Override
    public LockResult tryLock(Collection<String> lockKeys, int waitTime, int leaseTime) {
        return null;
    }

    @Override
    public LockResult tryLock(Collection<String> lockKeys, int waitTime, int leaseTime, TimeUnit unit) {
        return null;
    }

    @Override
    public void unlock(Lock lock) {
        lock.unlock();
    }
}
